#pragma once

#include "QueryRegexes.h"
#include "CompleteQuery.h"
#include "CustomException.h"
#include <vector>
#include <map>
#include <tuple>

class QueryPreprocessor{
private:
	std::string query; /**< The original query string */
	std::string result_parameter; /**< The result parameter */
	std::map<std::string, VAR_TYPE> declaration_parameters; /**< The declaration parameters */
	std::vector<std::tuple<QueryType, std::string, std::string>> suchthat_parameters; /**< All clauses led by such that */
	std::vector<std::tuple<std::string, std::string, std::string>> pattern_parameters; /**< All clauses led by pattern */
	
	/**
	 * Check whether the query is syntactically valid.
	 * @return true if the query is syntactically valid, false otherwise
	 */
	bool isSyntaxValid();
	
	/**
	 * Check whether the query is semantically valid.
	 * @return true if the query is semantically valid, false otherwise
	 */
	bool isContentValid();

	/**
	 * Facade function to call all other extractors.
	 */
	void extractAllParameters();

	/**
	 * Extract the result parameter. e.g: the synonym 'a' in Select a.
	 */
	void extractResultParameter();

	/**
	 * Extract the declaration parameters. e.g: a, a1, and w in assign a, a1; while w;
	 */
	void extractDeclarationParameters();

	/**
	 * Extract parameters(queries) led by the word such that. e.g: Modifies(a,"x") in Select a such that Modifies(a,"x")
	 */
	void extractSuchthatParameters();

	/**
	 * Extract parameters(queries) led by the word pattern. e.g: pattern a(_,_) in Select a pattern a(_,_)
	 */
	void extractPatternParameters();
public:
	/** Constructor
	 * Creates a QueryPreprocessor with the query as argument
	 * @param arg query string to be preprocessed
	 */
	QueryPreprocessor(std::string arg);

	/**
	 * Creates a CompleteQuery object to be evaluated by QueryEvaluator
	 * @return a CompleteQuery object if the query is deemed to be semantically correct
	 */
	CompleteQuery *buildQuery();
};